<?php
namespace library\tencent\wechat\common;
use library\common\arr;
use library\tencent\wechat\common\XmlUtils;
use phpDocumentor\Reflection\DocBlock\Tags\Var_;

/**
 * @summary 微信公众号支付接口 <http://dwz.cn/RhGbT>
 * @author Raven <karascanvas@qq.com>
 * @date 2015-06-19
 */
class EnterprisePay
{
    const API_URL = 'https://api.mch.weixin.qq.com/';
    const CUR_TYPE_CNY = 'CNY';
    const SIGN_TYPE_MD5 = 'MD5';
    const RESULT_SUCCESS = 'SUCCESS';
    const RESULT_FAIL = 'FAIL';
    const BILL_TYPE_ALL = 'ALL';
    const BILL_TYPE_SUCCESS = 'SUCCESS';
    const BILL_TYPE_REFUND = 'REFUND';
    const BILL_TYPE_REVOKED = 'REVOKED';
    const TRADE_TYPE_JSAPI = 'JSAPI';
    const TRADE_TYPE_NATIVE = 'NATIVE';
    const TRADE_TYPE_APP = 'APP';


    protected $config;


    public function __construct(array $config)
    {
        if (empty($config)) {
            throw new \InvalidArgumentException('Argument $config can not be empty.');
        }
        $defaults = array(
            'mch_appid'       => null,
            'mchid'      => null,
        );
        $this->config = array_merge($defaults, $config);
    }


    /**
     * 企业付款
     * @param array $params
     * @return array | false
     */
    public function transfers(array $params)
    {
        return $this->invoke('mmpaymkttransfers/promotion/transfers', $params);
    }

    /**
     * 通过错误代码获取错误信息
     * @param string $code
     * @return string
     */
    public function getErrorMessage($code)
    {
        $code = strtoupper($code);
        if (isset(static::$_error_map[$code])) {
            return static::$_error_map[$code];
        }
        return null;
    }


    protected function getConfig($key, $default = null)
    {
        if (isset($this->config[$key])) {
            return $this->config[$key];
        }
        return $default;
    }


    protected function generateNonceString()
    {
        return strtoupper(md5(uniqid(null, true)));
    }


    protected function filterParameters(array $params)
    {
        if (isset($params['sign'])) {
            unset($params['sign']);
        }
        $temp = array();
        foreach ($params as $key => $value) {
            if (!is_string($value) || $value != '') {
                $temp[$key] = $value;
            }
        }
        return $temp;
    }

    protected function sortParameters(array $params){
        $params = $this->filterParameters($params);
        ksort($params);
        reset($params);
        return $params;
    }


    protected function buildSignString(array $params)
    {

        $temp = array();
        foreach ($params as $key => $value) {
            $temp[] = $key . '=' . $value;
        }
        return implode('&', $temp);
    }


    protected function generateSign(array $params)
    {
        $params=$this->sortParameters($params);//排序，lsx20170528
        $prestr = $this->buildSignString($params);
        $new_prestr=$prestr.'&key='.$this->config['key'];
        return $this->generateSignMD5($new_prestr);
    }


    protected function generateSignMD5($prestr)
    {
        return strtoupper(md5($prestr));
    }


    protected function verifySign(array $params)
    {

        if (isset($params['sign'])) {
            return ($params['sign'] === $this->generateSign($params));
        }
        return false;
    }


    protected function invoke($path, array $params, $raw = false)
    {
        $params['mch_appid'] = $this->config['mch_appid'];
        $params['mchid'] = $this->config['mchid'];

        $params['nonce_str'] = $this->generateNonceString();
        $params=$this->sortParameters($params);//排序，lsx20170528
        $params['sign'] = $this->generateSign($params);
        $response = $this->httpPost(static::API_URL . $path, XmlUtils::serialize($params));
        if ($response === false) {
            return false;
        }
        if ($raw && strtolower(substr($response, 0, 5)) === '<xml>') {
            return $response;
        }
        return XmlUtils::deserialize($response);
    }


    protected function httpPost($url, $data)
    {
        $curl = curl_init();
//        curl_setopt_array($curl, array(
//            CURLOPT_URL            => $url,
//            CURLOPT_POSTFIELDS     => $data,
//            CURLOPT_HEADER         => false,
//            CURLOPT_AUTOREFERER    => false,
//            CURLOPT_RETURNTRANSFER => true,
//            CURLOPT_FOLLOWLOCATION => true,
//            CURLOPT_SSL_VERIFYPEER => false,
//        ));
        curl_setopt_array($curl, array(
            CURLOPT_URL            => $url,
            CURLOPT_POSTFIELDS     => $data,
            CURLOPT_HEADER         => false,
            CURLOPT_AUTOREFERER    => false,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_SSL_VERIFYPEER=>true,
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_SSLCERT=>getcwd().'/cert/apiclient_cert.pem',
            CURLOPT_SSLKEY=>getcwd().'/cert/apiclient_key.pem',
            CURLOPT_CAINFO=>getcwd().'/cert/rootca.pem',
        ));
        $response = curl_exec($curl);
        curl_close($curl);
        return $response;
    }


    protected function httpsPost($url, $data, $cacert_path)
    {
        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL            => $url,
            CURLOPT_POSTFIELDS     => $data,
            CURLOPT_HEADER         => false,
            CURLOPT_AUTOREFERER    => false,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_SSL_VERIFYHOST => 2,
            CURLOPT_CAINFO         => $cacert_path
        ));
        $response = curl_exec($curl);
        curl_close($curl);
        return $response;
    }


    private static $_error_map = array(
        'NOAUTH'                => '商户无此接口权限',
        'NOTENOUGH'             => '余额不足',
        'ORDERPAID'             => '商户订单已支付',
        'ORDERCLOSED'           => '订单已关闭',
        'SYSTEMERROR'           => '系统错误',
        'APPID_NOT_EXIST'       => 'APPID不存在',
        'MCHID_NOT_EXIST'       => 'MCHID不存在',
        'APPID_MCHID_NOT_MATCH' => 'appid和mch_id不匹配',
        'LACK_PARAMS'           => '缺少参数',
        'OUT_TRADE_NO_USED'     => '商户订单号重复',
        'SIGNERROR'             => '签名错误',
        'XML_FORMAT_ERROR'      => 'XML格式错误',
        'REQUIRE_POST_METHOD'   => '请使用post方法',
        'POST_DATA_EMPTY'       => 'post数据为空',
        'NOT_UTF8'              => '编码格式错误',
        'ORDERNOTEXIST'         => '此交易订单号不存在',
        'INVALID_TRANSACTIONID' => 'transaction_id无效',
        'PARAM_ERROR'           => '参数错误',
    );

}